package org.example.pinda.base;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.example.pinda.exception.code.ExceptionCode;

import java.util.Map;

/**
 * 通用返回类
 *
 * @author ryan fawcett
 * @see ExceptionCode
 */
@Getter
@Setter
@Accessors(chain = true) // 开启链式调用
@NoArgsConstructor
public class CommonResult<T> {
    public static final int FAIL_CODE = 0;
    public static final int SUCCESS_CODE = 200;
    public static final int TIMEOUT_CODE = -2;
    public static final String TIMEOUT_MESSAGE = "请求超时，请稍后再试";
    public static final String DEFAULT_ERROR_MESSAGE = "系统繁忙，请稍后再试";

    /**
     * 状态码
     *
     * @see ExceptionCode
     */
    @ApiModelProperty("状态码")
    private int code;
    /**
     * 请求数据
     */
    @ApiModelProperty("请求数据")
    private T data;
    /**
     * 提示信息
     */
    @ApiModelProperty("请求提示信息")
    private String msg;
    /**
     * 请求路径
     */
    @ApiModelProperty("请求路径")
    public String path;
    /**
     * 附加数据
     */
    @ApiModelProperty("附加数据")
    public Map<String, Object> extra;

    public CommonResult(int code, T data, String msg) {
        this.code = code;
        this.data = data;
        this.msg = msg;
    }

    public static <E> CommonResult<E> result(int code, E data, String msg) {
        return new CommonResult<>(code, data, msg);
    }

    /**
     * 携带请求数据的通用返回结果
     *
     * @param data 请求返回的数据
     * @param <E>  数据的类型
     * @return 通用返回对象
     */
    public static <E> CommonResult<E> success(E data) {
        return new CommonResult<>(SUCCESS_CODE, data, "ok");
    }

    /**
     * 携带请求数据和提示信息的通用返回结果
     *
     * @param data 请求返回的数据
     * @param msg  提示信息
     * @param <E>  数据的类型
     * @return 通用返回对象
     */
    public static <E> CommonResult<E> success(E data, String msg) {
        return new CommonResult<>(SUCCESS_CODE, data, msg);
    }

    /**
     * 携带状态码和提示信息的错误通用返回结果
     *
     * @param code 状态码
     * @param msg  提示信息
     * @param <E>  返回类型
     * @return 错误通用返回结果对象
     */
    public static <E> CommonResult<E> fail(int code, String msg) {
        return new CommonResult<>(code, null, msg);
    }

    /**
     * 携带提示信息的错误通用返回结果
     *
     * @param msg 提示信息
     * @param <E> 返回类型
     * @return 错误通用返回结果对象
     */
    public static <E> CommonResult<E> fail(String msg) {
        return new CommonResult<>(FAIL_CODE, null, msg);
    }

    /**
     * 携带提示信息和错误参数的通用返回结果
     *
     * @param msg  错误提示信息
     * @param args 错误的参数
     * @param <E>  返回的数据类型
     * @return 错误通用返回结果对象
     */
    public static <E> CommonResult<E> fail(String msg, Object... args) {
        msg = StrUtil.isEmpty(msg) ? DEFAULT_ERROR_MESSAGE : msg;
        return new CommonResult<>(FAIL_CODE, null, String.format(msg, args));
    }

    /**
     * 添加附加数据
     *
     * @param key   附加数据名称
     * @param value 附加数据值
     * @return 当前对象
     */
    public CommonResult<T> put(String key, Object value) {
        if (extra == null) {
            extra = MapUtil.newHashMap();
        }
        extra.put(key, value);
        return this;
    }

    /**
     * 逻辑处理是否成功
     *
     * @return 是否成功
     */
    public Boolean getIsSuccess() {
        return this.code == SUCCESS_CODE;
    }

    public static <E> CommonResult<E> timeout() {
        return fail(TIMEOUT_CODE, TIMEOUT_MESSAGE);
    }

}
